//
//  SLTimer.m
//  SLKit
//
//  Created by S_LINE on 2021/7/29.
//  Copyright © 2021 S_LINE. All rights reserved.
//

#import "SLTimer.h"


@interface SLTimer()

@property (nonatomic, assign) NSTimeInterval timeInterval;
@property (nonatomic, weak) id target;
@property (nonatomic, assign) BOOL repeats;
@property (nonatomic, assign) BOOL firstActionFired;
@property (nonatomic, copy) dispatch_block_t action;
@property (nonatomic, strong) dispatch_source_t timer_source;

@end

@implementation SLTimer

+ (instancetype)scheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval target:(id)aTarget repeats:(BOOL)repeats action:(dispatch_block_t)action
{
    return [[SLTimer alloc] initWithTimeInterval:timeInterval target:(id)aTarget repeats:repeats action:action];
}

- (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval target:(id)aTarget repeats:(BOOL)repeats action:(dispatch_block_t)action
{
    self = [super init];
    if (self)
    {
        self.timeInterval = timeInterval;
        self.target = aTarget;
        self.repeats = repeats;
        self.action = action;
        [self setupTimer];
    }
    return self;
}

- (void)setupTimer
{
    self.timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(self.timer_source, dispatch_walltime(NULL, 0), self.timeInterval * NSEC_PER_SEC, 0.0);
    __weak typeof(self) weakSelf = self;
    dispatch_source_set_event_handler(self.timer_source, ^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf.target)
        {
            [self invalidate];
            return;
        }
        if (strongSelf && strongSelf.action)
        {
            strongSelf.action();
            if (!strongSelf.repeats)
            {
                [strongSelf invalidate];
            }
        }
    });
    dispatch_resume(self.timer_source);
}

- (void)invalidate
{
    if (NULL != self.timer_source) {
        dispatch_source_cancel(self.timer_source);
    }
}

- (void)dealloc
{
    NSLog(@"%s", __func__);
    [self invalidate];
}

@end
